import android.app.AlertDialog;
import android.content.ContentValues;
import android.content.Context;
import android.content.DialogInterface;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Color;
import android.graphics.Point;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.GridLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.Toast;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2017/5/14 0014.
 */

public class GameView extends GridLayout {
    public MyDatabaseHelper dbHelper;

    public GameView(Context context, AttributeSet attrs,int defStyle){
        super(context,attrs,defStyle);

        initGameView();
    }

    public GameView(Context context){
        super(context);

        initGameView();
    }

    public GameView(Context context,AttributeSet attrs){
        super(context,attrs);

        initGameView();
    }

    //自定义类的入口方法
    private void initGameView(){
        //限制列数
        setColumnCount(4);
        //给GameView的背景颜色加上颜色
        setBackgroundColor(Color.parseColor("grey"));
        //创建手势操作
        setOnTouchListener(new OnTouchListener() {

            private float startX,startY,offsetX,offsetY;

            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()){
                    case MotionEvent.ACTION_DOWN:
                        startX = event.getX();
                        startY = event.getY();
                        break;
                    case MotionEvent.ACTION_UP:
                        offsetX = event.getX()-startX;
                        offsetY = event.getY()-startY;
                        //防止用户不是左右直线手势滑动而是斜方向滑动
                        if(Math.abs(offsetX)>(Math.abs(offsetY))){
                            //当手势往右滑动不太偏离水平的时候
                            if(offsetX<-5){
                                //手势往左
//                                System.out.println("向左滑动");
                                swipeLeft();
                            }else if(offsetY>5){
                                //手势往右
//                                System.out.println("向右滑动");
                                swipeRight();
                            }
                        }else{
                            //判断用户的手势上下滑动不太偏离垂直线
                            if(offsetY<-5){
                                //手势往上
//                                System.out.println("向上滑动");
                                swipeUp();
                            }else if(offsetY>5){
                                //手势往下
//                                System.out.println("向下滑动");
                                swipeDown();
                            }
                        }
                        break;
                }
                return true;
            }
        });
    }

    //自定义宽和高
    protected void onMeasure(int widthMeasureSpec,int heightMeasureSpec){
        super.onMeasure(widthMeasureSpec,heightMeasureSpec);

        int length = Math.min(getMeasuredHeight(),getMeasuredWidth());

        setMeasuredDimension(length,length);
    }

    //我们需要定义一个二维数组来记录GameView初始化时生成的16个卡片类
    private Card[][] cardsMap = new Card[4][4];
    //动态计算卡片的高和宽
    protected void onSizeChanged(int w,int h,int oldw,int oldh){
        super.onSizeChanged(w,h,oldw,oldh);
        //获取手机较窄的宽度，-10是用来间隔给个卡片的距离，用手机的宽除以4就是每个卡片的长度了
        int cardWidth = (Math.min(w,h)-10)/4;
        //初始的时候新建16个卡片
        addCards(cardWidth,cardWidth);

        startGame();
    }

    private void addCards(int cardWidth,int cardHeight){
        Card c;
        for(int y=0;y<4;y++){
            for (int x=0;x<4;x++){
                c = new Card(getContext());
                c.setNum(2);//给卡片设置初始化的数字
                addView(c,cardWidth,cardHeight);

                //初始化时新建的卡片类存放在下面新建的二维数组里
                cardsMap[x][y]=c;
            }
        }
    }

    //开始游戏生成随机数
    private void startGame(){

        MainActivity.getMainActivity().showMaxscore();

        //全部清空
        for(int y=0;y<4;y++) {
            for (int x = 0; x < 4; x++) {
                cardsMap[x][y].setNum(0);
            }
        }
        addRandomNum();
        addRandomNum();

    }

    //用来存放控制Card[][] cardsMap下标用的Point类的List集合
    private List<Point> emptyPoints = new ArrayList<Point>();
    //设置随机数,通过坐标轴给Card[][] cardsMap 里的每个card对象绑定上了Point，换句话说就是用 Point来记录每个Card所在的坐标轴，然后把Point存放在List集合里
    void addRandomNum(){
        emptyPoints.clear();//把这个point清空，每次调用添加随机数时就清空之前所控制的指针
        for(int y=0;y<4;y++){
            for(int x=0;x<4;x++){
                if(cardsMap[x][y].getNum()<=0){
                    emptyPoints.add(new Point(x,y));//给List存放控制卡片用的指标（通过坐标轴来控制）
                }
            }
        }
        //一个for循环走完我们就从List里取出一个控制指针的point对象
        Point p=emptyPoints.remove((int)(Math.random()*emptyPoints.size()));
        //通过point对象来充当下标的角色来控制存放card的二维数组cardsMap，然后随机给定位到的card对象赋值
        cardsMap[p.x][p.y].setNum(Math.random()>0.1?2:4);
    }
    //测试时用户手势的提示
    private void swipeLeft(){
//        Toast.makeText(getContext(),"向左滑动了",Toast.LENGTH_SHORT).show();
        boolean merge = false;//控制每滑动一次画面就加一个随机数

        for(int y=0;y<4;y++){
            for(int x=0;x<4;x++){
                for(int x1=x+1;x1<4;x1++){
                    //水平上固定了一个格子后再继续在水平上遍历别的格子，当格子有数的时候进行以下操作
                    if(cardsMap[x1][y].getNum()>0){
                        int a=cardsMap[x1][y].getNum();
                        //现在判断被固定的格子有没有数字，如果没有就进行以下操作
                        if(cardsMap[x][y].getNum()<=0){
                            //把与被固定的格子的同一水平上的格子的数字赋给被固定的格子
                            cardsMap[x][y].setNum(a);
                            //把值赋给被固定的格子后的格子清0
                            cardsMap[x1][y].setNum(0);
                            //第二层循环，即同一层的不同列退一格继续循环
                            // 这样做的原因是为了继续固定这个格子而去检查与它同一水平上的别的格子的内容，因为其他格子是什么个情况还需要继续在第二层进行判断
                            x--;
                            merge = true;//这个break为了在操作完这固定格子遍历的过程操作完后跳出遍历，因为只要有操作这个条件，就没有继续遍历下去的需要了
                        }else if(cardsMap[x][y].equals(cardsMap[x1][y])){
                            //判断相邻两个数相同的情况
                            cardsMap[x][y].setNum(cardsMap[x1][y].getNum()*2);
                            cardsMap[x1][y].setNum(0);

                            //在这要给MainActivity里的score加上分数
                            //而这里MainActivity设计成了单例设计模式，所以要使用get方法获得对象
                            MainActivity.getMainActivity().addScore(cardsMap[x][y].getNum());
                            //只要有一栋就要添加随机数
                            merge = true;
                        }
                        break;
                    }
                }
            }
        }
        if(merge){
            addRandomNum();
            checkComplete();
        }
    }
    private void swipeRight(){
//        Toast.makeText(getContext(),"向右滑动了",Toast.LENGTH_SHORT).show();
        boolean merge = false;//控制每滑动一次画面就加一个随机数

        for (int y = 0; y < 4; y++) {
            for (int x = 4-1; x >=0; x--) {
                for (int x1 = x-1; x1 >=0; x1--) {
                    if (cardsMap[x1][y].getNum()>0) {
                        if (cardsMap[x][y].getNum()<=0) {
                            cardsMap[x][y].setNum(cardsMap[x1][y].getNum());
                            cardsMap[x1][y].setNum(0);
                            x++;
                            //只要有移动就要加随机数
                            merge = true;
                        }else if (cardsMap[x][y].equals(cardsMap[x1][y])) {
                            cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2);
                            cardsMap[x1][y].setNum(0);
                            MainActivity.getMainActivity().addScore(cardsMap[x][y].getNum());
                            //只要有移动就要加随机数
                            merge = true;
                        }
                        break;
                    }
                }
            }
        }
        if (merge) {
            addRandomNum();
            checkComplete();
        }
    }
    private void swipeUp(){
//        Toast.makeText(getContext(),"向上滑动了",Toast.LENGTH_SHORT).show();
        boolean merge = false;//控制每滑动一次画面就加一个随机数

        for (int x = 0; x < 4; x++) {
            for (int y = 0; y < 4; y++) {
                for (int y1 = y+1; y1 < 4; y1++) {
                    if (cardsMap[x][y1].getNum()>0) {
                        if (cardsMap[x][y].getNum()<=0) {
                            cardsMap[x][y].setNum(cardsMap[x][y1].getNum());
                            cardsMap[x][y1].setNum(0);
                            y--;
                            //只要有移动就要加随机数
                            merge = true;
                        }else if (cardsMap[x][y].equals(cardsMap[x][y1])) {
                            cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2);
                            cardsMap[x][y1].setNum(0);
                            MainActivity.getMainActivity().addScore(cardsMap[x][y].getNum());
                            //只要有移动就要加随机数
                            merge = true;
                        }
                        break;
                    }
                }
            }
        }
        if (merge) {
            addRandomNum();
            checkComplete();
        }
    }
    private void swipeDown(){
//        Toast.makeText(getContext(),"向下滑动了",Toast.LENGTH_SHORT).show();
        boolean merge = false;//控制每滑动一次画面就加一个随机数

        for (int x = 0; x < 4; x++) {
            for (int y = 4-1; y >=0; y--) {
                for (int y1 = y-1; y1 >=0; y1--) {
                    if (cardsMap[x][y1].getNum()>0) {
                        if (cardsMap[x][y].getNum()<=0) {
                            cardsMap[x][y].setNum(cardsMap[x][y1].getNum());
                            cardsMap[x][y1].setNum(0);
                            y++;
                            merge = true;
                        }else if (cardsMap[x][y].equals(cardsMap[x][y1])) {
                            cardsMap[x][y].setNum(cardsMap[x][y].getNum()*2);
                            cardsMap[x][y1].setNum(0);
                            MainActivity.getMainActivity().addScore(cardsMap[x][y].getNum());
                            merge = true;
                        }
                        break;
                    }
                }
            }
        }
        if(merge){
            addRandomNum();
            checkComplete();
        }
    }

    //当所有的格子都有数字，所有相邻的格子都没有相同的数，就判定为失败，每次当用户发生手势滑动事件时判断
    public void checkComplete(){
        boolean Badcomplete = true;
        boolean Truecomplete = false;

        ALL:
            for(int y = 0;y<4;y++){
                for(int x = 0;x<4;x++){
                    if(cardsMap[x][y].getNum()==0 ||
                        (x>0&&cardsMap[x][y].equals(cardsMap[x-1][y])) ||
                        (x<4-1&&cardsMap[x][y].equals(cardsMap[x+1][y]))||
                        (y>0&&cardsMap[x][y].equals(cardsMap[x][y-1])) ||
                        (y<4-1&&cardsMap[x][y].equals(cardsMap[x][y+1]))){
                    //当上下左右都没有相同的
                        Badcomplete=false;
                    break ALL;
                    }
                }
            }

        ALL:
            for(int y = 0;y<4;y++){
                for(int x=0;x<4;x++){
                    if(cardsMap[x][y].getNum()==2048){
                        Truecomplete = true;
                        break ALL;
                    }
                }
            }
        if(Badcomplete){
            MainActivity.getMainActivity().saveScore();

            new AlertDialog.Builder(getContext()).setTitle("温馨提示").setMessage("游戏结束").setPositiveButton("重新开始", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {

                    startGame();
                }
            }).show();
        }
        if(Truecomplete){
            MainActivity.getMainActivity().saveScore();

            new AlertDialog.Builder(getContext()).setTitle("温馨提示").setMessage("成功通关").setPositiveButton("重新开始", new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    startGame();
                }
            }).show();
        }
    }

}